package huanzhao.erp.other.handler;

import cn.dev33.satoken.exception.NotLoginException;
import huanzhao.erp.domain.enumerate.error.ValidationError;
import huanzhao.erp.domain.exception.PhoneStateInconsistentException;
import huanzhao.erp.domain.exception.RateLimitException;
import huanzhao.erp.domain.exception.StaffNotFoundException;
import huanzhao.erp.domain.po.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;


/**
 * @author April
 * 2024/7/25 上午10:48
 * @version 1.0
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 处理参数校验异常
     *
     * @return ResponseEntity<String>
     * 2024/7/25 下午2:18:11
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ResponseEntity<Result<?>> handleValidationExceptions(ConstraintViolationException ex) {
        // 取出一个校验失败的错误信息
        ConstraintViolation<?> violation = ex.getConstraintViolations().iterator().next();
        String propertyPath = violation.getPropertyPath().toString();
        // 获取最后一个字段名
        String fieldName = propertyPath.substring(propertyPath.lastIndexOf(".") + 1);
        // 获取校验失败的错误信息
        String errorMessage = fieldName + violation.getMessage();
        // HTTP状态码设置为200
        return ResponseEntity.status(HttpStatus.OK).body(Result.error(ValidationError.PARAMETER_ERROR, errorMessage));
    }

    /**
     * 处理请求参数缺失异常
     *
     * @return ResponseEntity<Result>
     * 2024/7/25 下午2:34:48
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ResponseEntity<Result<?>> handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {
        String msg = "参数不存在：" + ex.getParameterName();
        return ResponseEntity.status(HttpStatus.OK).body(Result.error(msg));
    }

    @ExceptionHandler(value = MethodArgumentTypeMismatchException.class)
    public ResponseEntity<Result<?>> handleMethodArgumentTypeMismatchExceptionException(MethodArgumentTypeMismatchException ex) {
        String msg = "参数类型错误：" + ex.getParameter().getParameterName() + "，需要的类型为：" + ex.getRequiredType();
        return ResponseEntity.status(HttpStatus.OK).body(Result.error(msg));
    }

    /**
     * 处理超出接口访问数量限制异常
     *
     * @return ResponseEntity<Result>
     * 2024/7/25 下午2:17:05
     */
    @ExceptionHandler(value = RateLimitException.class)
    public ResponseEntity<Result<?>> handleRateLimitException(RateLimitException ex) {
        String message = ex.getMessage();
        if (ex.getTtl() > 0) {
            message += "，请 " + formatTime(ex.getTtl()) + "后再试";
        }
        return ResponseEntity.status(HttpStatus.OK).body(Result.error(message));
    }


    /**
     * 处理手机状态不一致异常
     *
     * @return ResponseEntity<Result < ?>>
     * 2024/10/13 23:06:48
     */
    @ExceptionHandler(value = PhoneStateInconsistentException.class)
    public ResponseEntity<Result<?>> handlePhoneStateInconsistentException(PhoneStateInconsistentException ex) {
        String message = ex.getMessage();
        return ResponseEntity.status(HttpStatus.OK).body(Result.error(message));
    }

    /**
     * 处理未登录异常
     *
     * @param ex 未登录异常
     * @return ResponseEntity<Result < ?>>
     * 2024/10/3 20:21:08
     */
    @ExceptionHandler(value = NotLoginException.class)
    public ResponseEntity<Result<?>> handleNotLoginException(NotLoginException ex) {
        return ResponseEntity.status(HttpStatus.OK).body(Result.error("请先登录"));
    }

    /**
     * 处理员工不存在异常
     *
     * @param ex 员工不存在异常
     * @return ResponseEntity<Result < ?>>
     * 2024/10/4 17:42:56
     */
    @ExceptionHandler(value = StaffNotFoundException.class)
    public ResponseEntity<Result<?>> handleStaffNotFoundException(StaffNotFoundException ex) {
        return ResponseEntity.status(HttpStatus.OK).body(Result.error("员工不存在"));
    }

    /**
     * 处理全局异常
     *
     * @return ResponseEntity<Result < ?>>
     * 2024/7/28 下午7:31:19
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseEntity<Result<?>> handleBlockException(Exception ex) {
        log.error("服务器内部错误", ex);
        String message = "服务器内部错误，请联系开发人员，错误原因：" + ex.getMessage();
        return ResponseEntity.status(HttpStatus.OK).body(Result.error(message));
    }

    /**
     * 格式化时间
     *
     * @param seconds 秒数
     * @return String
     * 2024/7/28 下午8:07:25
     */
    private String formatTime(long seconds) {
        long hours = seconds / 3600;
        long minutes = (seconds % 3600) / 60;
        long sec = seconds % 60;
        String hour = hours > 0 ? hours + "小时" : "";
        String minute = minutes > 0 ? minutes + "分" : "";
        String second = sec + "秒";
        return hour + minute + second;
    }
}

